﻿using Microsoft.TeamFoundation.Client;
using Pyramid.VsOnline.Core.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace Pyramid.VsOnline.Core.Services
{
    public sealed class TfsParamParser
    {
        public TfsParameters Parse(string[] arguments)
        {
            var tfsParams = ParseWorkspaces(arguments);
            if(tfsParams==null)
            {
                tfsParams = ParseWorkfold(arguments);
            }
            if (tfsParams == null)
            {
                tfsParams = ParseCreateWorkspace(arguments);
            }
            if(tfsParams == null)
            {
                tfsParams = ParseDeleteWorkspace(arguments);
            }
            if (tfsParams == null)
            {
                tfsParams = ParseLatestVersion(arguments);
            }
            if (tfsParams == null)
            {
                tfsParams = ParseHistory(arguments);
            }
            ParseCommonParams(arguments, tfsParams);
            if (tfsParams.Workfold != null && tfsParams.Workfold.Owner == null)
                tfsParams.Workfold.Owner = tfsParams.LoginName;
            return tfsParams;
        }
        private void ParseCommonParams(IEnumerable<string> arguments, TfsParameters tfsParams)
        {
            var argsList = arguments.ToList();
            var loginIndex = argsList.FindIndex(a => a.StartsWith("-login:"));
            if(loginIndex>=0)
            {
                var credentials = argsList[loginIndex].Replace("-login:", "");
                var creds = credentials.Split(new char[] { ',' });
                var userName = creds[0];
                var password = creds[1];
                tfsParams.LoginName = userName;
                var tfsCredentials = GetTfsCredentials(userName, password);
                tfsParams.Credentials = tfsCredentials;
            }
            var serverIndex = argsList.FindIndex(a => a.StartsWith("-server:"));
            if (serverIndex >= 0)
            {
                tfsParams.ServerUrl = argsList[serverIndex].Replace("-server:", "");
            }
            tfsParams.Silent = false; // argsList.Exists(a => a.StartsWith("-noprompt"));
        }

        private TfsParameters ParseWorkspaces(IEnumerable<string> arguments)
        {
            var argsList = arguments.ToList();
            var isWorkspaces = argsList[0].ToLower() == "workspaces";
            if (!isWorkspaces) return null;
            var isFormatDetailed = argsList.Exists(a => a.ToLower() == "-format:detailed");
            var tfsParams = new TfsParameters { IsWorkspaces = true, Workspaces = new WorkspacesParameters() };
            tfsParams.Workspaces.Format = isFormatDetailed ? WorkspaceFormatType.Detailed : WorkspaceFormatType.Brief;

            var workspaceIndex = argsList.FindIndex(a => a.StartsWith("-workspace:"));
            tfsParams.Workspaces.WorkspaceName = workspaceIndex > -1 ? argsList[workspaceIndex].Replace("-workspace:", "") : null;
            
            var ownerIndex = argsList.FindIndex(a => a.StartsWith("-owner:"));
            tfsParams.Workspaces.Owner = ownerIndex > -1 ? argsList[ownerIndex].Replace("-owner:", "") : null;

            var computerIndex = argsList.FindIndex(a => a.StartsWith("-computer:"));
            tfsParams.Workspaces.Computer = computerIndex > -1 ? argsList[computerIndex].Replace("-computer:", "") : null;

            return tfsParams;
        }
        private TfsParameters ParseCreateWorkspace(IEnumerable<string> arguments)
        {
            var argsList = arguments.ToList();
            var isWorkspace = argsList[0].ToLower() == "workspace";
            var isNew = argsList[1].ToLower() == "-new";
            if (!(isWorkspace && isNew)) return null;
            var workspaceInfos = argsList[2].Split(new char[]{';'});

            var tfsParams = new TfsParameters { IsCreateWorkspace = true, WorkspaceCreate = new WorkspaceCreateParameters() };
            tfsParams.WorkspaceCreate.WorkspaceName = workspaceInfos[0];
            tfsParams.WorkspaceCreate.Owner = workspaceInfos[1];

            var computerIndex = argsList.FindIndex(a => a.StartsWith("-computer:"));
            tfsParams.WorkspaceCreate.Computer = computerIndex > -1 ? argsList[computerIndex].Replace("-computer:", "") : null;

            return tfsParams;
        }
        private TfsParameters ParseDeleteWorkspace(IEnumerable<string> arguments)
        {
            var argsList = arguments.ToList();
            var isWorkspace = argsList[0].ToLower() == "workspace";
            var isDelete = argsList[1].ToLower() == "-delete";
            if (!(isWorkspace && isDelete)) return null;
            var workspaceInfos = argsList[2].Split(new char[] { ';' });

            var tfsParams = new TfsParameters { IsDeleteWorkspace = true, WorkspaceDelete = new WorkspaceDeleteParameters() };
            tfsParams.WorkspaceDelete.WorkspaceName = workspaceInfos[0];
            tfsParams.WorkspaceDelete.Owner = workspaceInfos[1];

            return tfsParams;
        }
        private TfsParameters ParseWorkfold(IEnumerable<string> arguments)
        {
            var argsList = arguments.ToList();
            var isWorkfold = argsList[0].ToLower() == "workfold";
            var mapIndex = argsList.FindIndex(a => a.ToLower() == "-map");
            var workspaceIndex = argsList.FindIndex(a => a.StartsWith("-workspace:"));
            if (!isWorkfold) return null;
            var tfsParams = new TfsParameters { IsWorkfold = true, Workfold = new WorkfoldParameters() };
            tfsParams.Workfold.ServerProjectPath = argsList[mapIndex + 1];
            
            string targetPath=null;
            string serverUrl=null;
            ParseTargetPathAndServerUrl(argsList[mapIndex + 2], out targetPath, out serverUrl);
            tfsParams.Workfold.TargetPath = targetPath;
            if(serverUrl!=null) tfsParams.ServerUrl = serverUrl;

            tfsParams.Workfold.Workspace = workspaceIndex>-1?argsList[workspaceIndex].Replace("-workspace:", ""):null;
            return tfsParams;
        }
        private void ParseTargetPathAndServerUrl(string path, out string targetPath, out string serverUrl)
        {
            targetPath = path;
            serverUrl = null;
            if (path != null && path.Contains(";"))
            {
                var workspaceNameAndServer = path.Split(new char[] { ';' });
                targetPath = workspaceNameAndServer[0];
                serverUrl = workspaceNameAndServer[1];
            }
        }
        private TfsParameters ParseLatestVersion(IEnumerable<string> arguments)
        {
            var argsList = arguments.ToList();
            var isGetLatestVersion = argsList[0].ToLower() == "get";
            if (!isGetLatestVersion) return null;
            var tfsParams = new TfsParameters { IsGetLatestVersion = true, LatestVersion = new LatestVersionParameters() };
            string targetPath = null;
            string serverUrl = null;
            ParseTargetPathAndServerUrl(argsList[1], out targetPath, out serverUrl);
            tfsParams.LatestVersion.TargetPath = targetPath;
            if (serverUrl != null) tfsParams.ServerUrl = serverUrl;

            tfsParams.LatestVersion.IsRecursive = argsList.Exists(a => a.ToLower() == "-recursive");
            var versionIndex = argsList.FindIndex(a => a.ToLower().StartsWith("-version:"));
            if (versionIndex >= 0)
            {
                var historyVersions = argsList[versionIndex].Replace("-version:", "").Split(new char[] { '~' });
                if (historyVersions.Length > 0)
                    tfsParams.LatestVersion.VersionFrom = DateTime.ParseExact(historyVersions[0], "Dyyyy-MM-ddTHH:mm:ssZ", null).ToUniversalTime();
                if (historyVersions.Length > 1)
                    tfsParams.LatestVersion.VersionTo = DateTime.ParseExact(historyVersions[1], "Dyyyy-MM-ddTHH:mm:ssZ", null).ToUniversalTime();
            }
            //tfsParams.LatestVersion.ServerProjectPath = "$/Pyramid Templates/OnionArch_MVC/Trunk";
            return tfsParams;
        }
        private TfsParameters ParseHistory(IEnumerable<string> arguments)
        {
            var argsList = arguments.ToList();
            var historyIndex = argsList.FindIndex(a=>a.ToLower() == "history");
            if (historyIndex < 0) return null;
            var isFormatDetailed = argsList.Exists(a => a.ToLower() == "-format:detailed");
            var tfsParams = new TfsParameters { IsGetHistory = true, History = new HistoryParameters() };
            tfsParams.History.ServerProjectPath = argsList[historyIndex + 1];
            tfsParams.History.Format = isFormatDetailed?WorkspaceFormatType.Detailed:WorkspaceFormatType.Brief;
            tfsParams.History.IsRecursive = argsList.Exists(a => a.ToLower() == "-recursive");
            var versionIndex = argsList.FindIndex(a => a.ToLower().StartsWith("-version:"));
            if (versionIndex >= 0)
            {
                var historyVersions = argsList[versionIndex].Replace("-version:", "").Split(new char[] { '~' });
                if (historyVersions.Length > 0)
                    tfsParams.History.VersionFrom = DateTime.ParseExact(historyVersions[0], "Dyyyy-MM-ddTHH:mm:ssZ", null).ToUniversalTime();
                if (historyVersions.Length > 1)
                    tfsParams.History.VersionTo = DateTime.ParseExact(historyVersions[1], "Dyyyy-MM-ddTHH:mm:ssZ", null).ToUniversalTime();
            }
            return tfsParams;
        }
        private static TfsClientCredentials GetTfsCredentials(string userName, string password)
        {
            var networkCreds= new NetworkCredential(userName, password);
            var basicCreds = new BasicAuthCredential(networkCreds);
            var tfsCreds = new TfsClientCredentials(basicCreds)
            {
                AllowInteractive = false
            };
            return tfsCreds;
        }
    }
}
